Skip to content

feat(cli): lem update — self-update from GitHub releases with version-derived channels#15

Merged
Snider merged 1 commit into
devfrom
feat/self-update
Jul 22, 2026
Merged

feat(cli): lem update — self-update from GitHub releases with version-derived channels#15
Snider merged 1 commit into
devfrom
feat/self-update

Conversation

@Snider

@Snider Snider commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

lem update / --check / --channel=<stable|beta|alpha|dev> on dappco.re/go/update v0.13.0. The channel derives from the binary's own version (a v1.2.3-beta.1 binary follows beta; dev-<sha> follows the rolling dev release by literal tag — never semver-compared), which makes release channels a side effect of how a build is versioned.

  • Asset self-selection against the Driver/Native grid: GOOS/GOARCH mapped to the grid names (darwin→macos, amd64→x86_64, arm64→aarch64), backend from the new -X main.backend ldflag, Native-vs-Driver role from the invoked binary's name (the only distinguishing signal — one build feeds both zips; documented limitation). Zero/multiple matches fail loudly naming the search.
  • Zip apply rides upstream: assets are zip-packaged, so the update path downloads → extracts the single binary in memory → updater.DoUpdateFromReader (added upstream in v0.13.0 for exactly this, with VersionCheckResult and GetReleaseByTag) — go-update's real apply/rollback, not a fork.
  • build.yml: cpu + metal cells stamp -X main.backend; the release job now publishes prerelease: true for any tag containing - (was always false — an -rc.1 tag would have landed in the stable channel).
  • Known residual: GitLab's Makefile cells (amd/cuda/cpu-*) don't stamp backend yet — those binaries fail asset-selection loudly rather than guessing; follow-up threads the ldflag through the Makefile.
  • Tests: channel derivation + command flows + asset matrix, all through go-update's NewGithubClient mock seam, no live network. 807 green.

🤖 Generated with Claude Code
Co-Authored-By: Virgil virgil@lethean.io

Adds `lem update` (+ --check, --channel override), using dappco.re/go/update
v0.13.0's primitives. The default channel is derived from the running
binary's own stamped version (deriveUpdateChannel): a v1.2.3 build follows
stable, v1.2.3-beta.1 follows beta, v1.2.3-alpha.2 follows alpha, and a
dev-<sha12> build follows the rolling dev prerelease — release channels as
a side effect of the version string, not a separately tracked setting.

Asset self-selection (selectReleaseAsset/updateAssetPrefix) replaces
go-update's GetDownloadURL: this repo's asset names spell os/arch as
macos/x86_64/aarch64, which never match runtime.GOOS/GOARCH substrings
(darwin never appears in a macos-* name), so lem maps the dimensions itself
and exact-prefix-matches against release.Assets. Zero or multiple matches is
a loud typed error naming what was looked for. Native vs Driver role comes
from the invoked binary's own name — the only signal that exists, since
build.yml compiles one binary per cell and copies it into both zips after
the fact, so no ldflags var could distinguish them.

The zip problem: every release asset is a zip holding one binary (never a
raw binary stream), so go-update's own DoUpdate — which feeds an HTTP
response body straight into selfupdate.Apply — cannot be used directly.
applyReleaseAsset downloads and unzips here, then hands the extracted binary
bytes to go-update's new DoUpdateFromReader, reusing its apply/rollback
machinery instead of re-implementing it.

The dev channel is fetched by its exact tag (GetReleaseByTag) rather than
through channel classification, and compared by plain string inequality
against the asset's own embedded version — never a semver.Compare on a
rolling tag. The semver channels go through CheckForNewerVersion, unpacked
via the new VersionCheckResult interface so this reuses go-update's own
comparison instead of re-implementing it.

CI: build.yml now stamps -X main.backend=<cpu|metal> alongside main.version
for the cpu and metal cells (asset-selection needs it), and a tag containing
'-' (v1.2.3-beta.1) now publishes prerelease: true instead of every v* tag
always publishing false, so go-update's channel filter sees prerelease tags
correctly.

Co-Authored-By: Virgil <virgil@lethean.io>
@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 554048c5-4d5b-4945-b55e-058171697b95

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Warning

Billing warning: we have not been able to collect payment for this subscription for more than 72 hours. Please update the payment method or pay any pending invoices in Billing to avoid service interruption.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@sonarqubecloud

Copy link
Copy Markdown

@Snider
Snider merged commit 1582c44 into dev Jul 22, 2026
5 of 6 checks passed
@Snider
Snider deleted the feat/self-update branch July 22, 2026 16:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant